package fem2.material;

import inf.jlinalg.IVector;

import org.junit.Test;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Debugger;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.PatchTestQ4;
import fem2.PatchTestT3;
import fem2.analysis.Analysis;
import fem2.analysis.LinearStaticAnalysis;
import fem2.element.StructuralElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;

public class PatchTestMLSStressRecovery extends AbstractStructuralStaticDemo {

	int option = 0;

	@Override
	public Mesh createMesh() {
		switch (option) {
		case 0:
			return new PatchTestT3(0).createMesh();
		case 1:
			return new PatchTestQ4(0).createMesh();
		default:
			throw new Error("invalid option");
		}
	}

	@Override
	public Model createConditions(Model m) {
		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 2;
		double nu = 0.3;
		double t = 1.0;
		State ss = State.PLANE_STRESS;
		double r = 2;
		MaterialModel mm = new MLSrecoveryMM(m, new StVenantKirchhoffMM(E, nu, t, 0, ss), r);
		return mm;
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		return new StructuralElement(mp, mm);
	}

	@Test
	public void test1() {
		option = 0;
		Model m = createModel();
		Mesh mesh = m.getMesh();

		double du = 2;
		Constraint c1 = new Constraint(false, false);
		c1.setValue(0, du);
		Constraint c2 = new Constraint(false, true);
		c2.setValue(0, du);

		mesh.setConstraint(c2, MeshUtilities.seekNodesOnSurface(mesh, 1, 0, -1));
		MeshUtilities.seekNode(mesh, 1, 0).setConstraint(c1);

		Analysis an = new LinearStaticAnalysis(m);
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);
		an.run();

		StressRecoveryMM mm = (StressRecoveryMM) ((StructuralElement) m.getElement(0))
				.getMaterialModel();

		for (int i = 0; i < m.countElements(); i++) {
			StructuralElement se = (StructuralElement) m.getElement(i);
			int ng = se.getNumIntegrationPoints();
			for (int j = 0; j < ng; j++) {
				Debugger.watch("real stress " + i + ", " + j + " = ", se.getStress(j));
			}
		}
		for (int i = 0; i < mesh.countNodes(); i++) {
			IVector s = mm.computeRecoverStress(mesh.getNode(i));
			Debugger.watch("recover stress " + i + " =", s);
		}
	}

	@Test
	public void test2() {
		option = 1;
		Model m = createModel();
		Mesh mesh = m.getMesh();

		double du = 2;
		Constraint c1 = new Constraint(false, false);
		c1.setValue(0, du);
		Constraint c2 = new Constraint(false, true);
		c2.setValue(0, du);

		mesh.setConstraint(c2, MeshUtilities.seekNodesOnSurface(mesh, 1, 0, -1));
		MeshUtilities.seekNode(mesh, 1, 0).setConstraint(c1);

		Analysis an = new LinearStaticAnalysis(m);
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);
		an.run();

		StressRecoveryMM mm = (StressRecoveryMM) ((StructuralElement) m.getElement(0))
				.getMaterialModel();

		for (int i = 0; i < m.countElements(); i++) {
			StructuralElement se = (StructuralElement) m.getElement(i);
			int ng = se.getNumIntegrationPoints();
			for (int j = 0; j < ng; j++) {
				Debugger.watch("real stress " + i + ", " + j + " = ", se.getStress(j));
			}
		}
		for (int i = 0; i < mesh.countNodes(); i++) {
			IVector s = mm.computeRecoverStress(mesh.getNode(i));
			Debugger.watch("recover stress " + i + " =", s);
		}
	}

}
